import time
import pyaudio
import wave
import requests
import base64
import json
import spacy
from collections import defaultdict

# 百度语音识别配置
API_KEY = "你的API_KEY"
SECRET_KEY = "你的SECRET_KEY"
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "input.wav"

# NLP配置（需提前下载中文模型：python -m spacy download zh_core_web_sm）
nlp = spacy.load("zh_core_web_sm")

# 知识库
knowledge_base = {
    "你好": "你好！我是语音答疑助手，有什么可以帮你？",
    "今天天气怎么样": "抱歉，我暂时无法获取实时天气，但你可以问我其他问题。",
    "什么是人工智能": "人工智能是指让计算机系统具备类似人类的感知、学习和决策能力的技术。",
    "如何学习编程": "学习编程需要多练习、多实践，建议从Python或JavaScript开始入门。",
    "时间": f"现在是{time.strftime('%Y年%m月%d日 %H:%M:%S', time.localtime())}"
}

def get_access_token():
    """获取百度语音识别API令牌"""
    url = f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={API_KEY}&client_secret={SECRET_KEY}"
    return requests.get(url).json()["access_token"]

def record_audio():
    """录制音频"""
    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
    print("请说话...")
    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)
    stream.stop_stream()
    stream.close()
    p.terminate()
    with wave.open(WAVE_OUTPUT_FILENAME, 'wb') as wf:
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
    return WAVE_OUTPUT_FILENAME

def audio_to_text(audio_file):
    """音频转文本"""
    access_token = get_access_token()
    url = f"https://vop.baidu.com/server_api?access_token={access_token}"
    with open(audio_file, 'rb') as f: audio_data = f.read()
    audio_base64 = base64.b64encode(audio_data).decode('utf-8')
    params = {
        "format": "wav", "rate": 16000, "channel": 1,
        "cuid": "voice_assistant", "speech": audio_base64, "len": len(audio_data)
    }
    headers = {"Content-Type": "application/json"}
    try:
        response = requests.post(url, data=json.dumps(params), headers=headers)
        result = response.json()
        return result.get("result", ["识别失败"])[0] if result.get("err_no") == 0 else "识别错误"
    except Exception as e:
        return f"请求错误: {str(e)}"

def recognize_intent(text):
    """识别意图"""
    doc = nlp(text)
    intent = "未知"
    keywords = [("天气", "天气查询"), ("人工智能", "概念解释"),
                ("编程", "学习建议"), ("时间", "时间查询"), ("你好", "问候")]
    for keyword, intent_type in keywords:
        if keyword in text:
            intent = intent_type
            break
    location = next((ent.text for ent in doc.ents if ent.label_ == "GPE"), None)
    return {"intent": intent, "location": location, "text": text}

def generate_answer(intent_info):
    """生成回答"""
    text = intent_info["text"]
    if text in knowledge_base: return knowledge_base[text]
    intent, location = intent_info["intent"], intent_info["location"]
    if intent == "天气查询" and location:
        return f"{location}的天气信息我暂时无法获取，请使用天气应用查询。"
    elif intent == "天气查询":
        return "你可以问我‘XX地方的天气怎么样’来查询天气。"
    elif intent in ["概念解释", "学习建议"]:
        return "这个问题需要更详细的说明，你可以具体描述需求吗？"
    elif intent == "时间查询":
        return f"现在是{time.strftime('%Y年%m月%d日 %H:%M:%S', time.localtime())}"
    elif intent == "问候":
        return "你好！很高兴为你服务。"
    else:
        return "抱歉，这个问题我还在学习中，你可以换个问题试试。"

def voice_answer_system():
    """语音答疑系统主流程"""
    print("语音答疑系统启动...（按Ctrl+C退出）")
    while True:
        try:
            # 1. 录音
            audio_file = record_audio()
            # 2. 语音识别
            text = audio_to_text(audio_file)
            print(f"识别文本: {text}")
            if text in ["识别错误", "请求错误"]:
                print("回答: 语音识别失败，请重试。")
                continue
            # 3. NLP处理
            intent_info = recognize_intent(text)
            answer = generate_answer(intent_info)
            print(f"回答: {answer}")
            print("-" * 50)
        except KeyboardInterrupt:
            print("\n系统退出，再见！")
            break
        except Exception as e:
            print(f"系统错误: {str(e)}")
            continue

if __name__ == "__main__":
    voice_answer_system()